package io.github.wanggit.tracing.agent;

import java.lang.instrument.Instrumentation;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class TracingAgent {

    public static void premain(String agentArgs, Instrumentation instrumentation) {
        printBanner();
        Args args = parseAgentArgs(agentArgs);
        printArgs(args);
        instrumentation.addTransformer(new TracingClassFileTransformer(args));
    }

    static void printBanner() {
        System.out.println(
                "AntRPC Tracing Agent starting...."
                        + System.lineSeparator()
                        + "Syntax: -javaagent:/path/tracing-agent.jar[=package1[,package1...]:true|false]"
                        + System.lineSeparator()
                        + "Example: -javaagent:/path/tracing-agent.jar=io.github.wanggit,com.company.pjt,com.company.common:true"
                        + System.lineSeparator());
    }

    static void printArgs(Args args) {
        System.out.println(
                "Tracing Package Prefix: "
                        + args.getPkcPrefixs()
                        + System.lineSeparator()
                        + "Show ClassFileTransformer Log: "
                        + args.isShowLog());
    }

    static Args parseAgentArgs(String agentArgs) {
        String[] tmps = null == agentArgs ? new String[] {} : agentArgs.split(":");
        if (tmps.length > 2) {
            throw new RuntimeException("Agent Args Format ERROR: " + agentArgs);
        }
        List<String> pkgPrefixs = new ArrayList<>();
        if (tmps.length > 0) {
            String[] pkgs = tmps[0].trim().split(",");
            for (String pkg : pkgs) {
                String pkgVal = pkg.trim();
                if (pkgVal.length() > 0) {
                    pkgPrefixs.add(pkgVal.replaceAll("\\.", "/"));
                }
            }
        }
        boolean showLog = tmps.length > 1 && Objects.equals(tmps[1].trim().toLowerCase(), "true");
        return new Args(pkgPrefixs, showLog);
    }

    static class Args {
        private final List<String> pkcPrefixs;

        private final boolean showLog;

        public Args(List<String> pkcPrefixs, boolean showLog) {
            this.pkcPrefixs = pkcPrefixs;
            this.showLog = showLog;
        }

        public List<String> getPkcPrefixs() {
            return pkcPrefixs;
        }

        public boolean isShowLog() {
            return showLog;
        }
    }
}
